﻿
/**
 * @ProjectName: 
 * @Copyright: 2014 lisheng  All Right Reserved.
 * @address: toughheart@163.com
 * @date: 2015年1月3日 下午12:36:44
 * @Description: 本内容未经本人允许禁止使用、转发.
 */
 
package com.ls.fw.data.search.impl.dao.base;

import java.io.File;
import java.io.StringReader;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.DoubleField;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.document.FieldType;
import org.apache.lucene.document.FloatField;
import org.apache.lucene.document.IntField;
import org.apache.lucene.document.LongField;
import org.apache.lucene.document.StringField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.MatchAllDocsQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.Sort;
import org.apache.lucene.search.SortField;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.search.highlight.Formatter;
import org.apache.lucene.search.highlight.Fragmenter;
import org.apache.lucene.search.highlight.Highlighter;
import org.apache.lucene.search.highlight.QueryScorer;
import org.apache.lucene.search.highlight.SimpleHTMLFormatter;
import org.apache.lucene.search.highlight.SimpleSpanFragmenter;

import com.ls.fw.common.utils.ObjectUtil;
import com.ls.fw.data.bean.Column;
import com.ls.fw.data.bean.Order;
import com.ls.fw.data.bean.Order.OrderType;
import com.ls.fw.data.bean.PageBean;
import com.ls.fw.data.dao.DaoAdapter;
import com.ls.fw.data.exception.DataException;
import com.ls.fw.data.exp.Where;
import com.ls.fw.data.search.impl.lucene.bean.ValueType;
import com.ls.fw.data.search.impl.lucene.handler.BeanHandler;
import com.ls.fw.data.search.impl.lucene.mapper.DocMapper;
import com.ls.fw.data.search.impl.lucene.server.LuceneServer;
import com.ls.fw.data.search.impl.lucene.server.DefaultLuceneServer;
import com.ls.fw.data.search.impl.lucene.statement.WhereParser;
import com.ls.fw.data.search.impl.lucene.util.BeanParameterUtil;
import com.ls.fw.data.search.impl.lucene.util.IndexUtil;
import com.ls.fw.data.search.impl.lucene.util.LuceneUtil;
import com.ls.fw.data.statement.Select;
import com.mysema.query.DefaultQueryMetadata;
import com.mysema.query.QueryMetadata;
import com.mysema.query.lucene.LuceneQuery;
import com.mysema.query.lucene.LuceneSerializer;
import com.mysema.query.types.path.DatePath;
import com.mysema.query.types.path.DateTimePath;
import com.mysema.query.types.path.NumberPath;
import com.mysema.query.types.path.PathBuilder;
import com.mysema.query.types.path.StringPath;
import com.mysema.query.types.path.TimePath;


/**
 * 
 * @author lisheng
 * @date 2015年1月3日 下午12:36:44
 * @version V1.0 
 */
public abstract class BaseLuceneDaoAdapter extends DaoAdapter implements BaseLuceneDao{

	protected LuceneServer server = null;

	protected LuceneQuery query;

	protected final QueryMetadata metadata = new DefaultQueryMetadata();

	protected final PathBuilder<Object> entityPath = new PathBuilder<Object>(
			Object.class, "obj");

	protected BeanHandler beanHandler = new BeanHandler();

	public BaseLuceneDaoAdapter() {
		super();
	}

	/**
	 * @param address
	 */
	public BaseLuceneDaoAdapter(String address) {
		super();
		this.address = address;
		server = new DefaultLuceneServer(address);
	}

	/**
	 * @param address
	 * @param autoCommit
	 */
	public BaseLuceneDaoAdapter(String address, boolean autoCommit) {
		this.address = address;
		server = new DefaultLuceneServer(address);
		this.autoCommit = autoCommit;
	}


	public void setServer(LuceneServer server) {
		this.server = server;
	}

	@Override
	public boolean commit(boolean softCommit) {
		this.server.commit();
		return true;
	}

	@Override
	public void close() {
		super.close();
		try {
			this.server.close();
		} catch (DataException e) {
			throw e;
		} catch (Exception e) {
			throw new DataException(e.getMessage(),e);
		}
	}

	private void init() {
		String indexFilePath = address.toString();
		final File docDir = new File(indexFilePath);
		if (!docDir.exists()) {
			docDir.mkdirs();
		}
	}

	@Override
	public void setAddress(Object address) {
		super.setAddress(address);
		init();
	}

	@Override
	public <S> S switchServer(Object address) {
		server.reopen(address.toString());
		return (S) server;
	}

	@Override
	public boolean open(Object address) {
		boolean flag = server.open(address.toString());
		this.query = this.getNewQuery();
		return flag;
	}

	public LuceneQuery getQuery() {
		return query;
	}

	public LuceneQuery getNewQuery(boolean lowerCase, boolean splitTerms) {
		IndexSearcher searcher = server.acquire();
		LuceneQuery query = new LuceneQuery(this.getNewLuceneSerializer(
				lowerCase, splitTerms), searcher);
		return query;
	}

	public LuceneQuery getNewQuery() {
		return this.getNewQuery(false, false);
	}

	public LuceneSerializer getNewLuceneSerializer(boolean lowerCase,
			boolean splitTerms) {
		LuceneSerializer ls = new LuceneSerializer(lowerCase, splitTerms);
		return ls;
	}

	public LuceneSerializer getNewLuceneSerializer() {
		return this.getNewLuceneSerializer(false, false);
	}

	public PathBuilder<Object> getQueryBuilder() {
		return this.entityPath;
	}

	@Override
	public StringPath getStringItem(String name) {
		return entityPath.getString(name);
	}

	@Override
	public <T extends Number & Comparable<?>> NumberPath<T> getNumberItem(
			String name, Class<T> type) {
		return entityPath.getNumber(name, type);
	}

	@Override
	public <T extends Comparable<?>> DatePath<T> getDateItem(String name,
			Class<T> type) {
		return entityPath.getDate(name, type);
	}

	@Override
	public <T extends Comparable<?>> TimePath<T> getTimeItem(String name,
			Class<T> type) {
		return entityPath.getTime(name, type);
	}

	@Override
	public <T extends Comparable<?>> DateTimePath<T> getDateTimeItem(
			String name, Class<T> type) {
		return entityPath.getDateTime(name, type);
	}

	@Override
	public <M> Document getDocument(final M model) {
		Document doc = new Document();
		try {
			List<Column> list = beanHandler.toColumns(model);
			if (list != null) {
				for (Column column : list) {
					Field field = this.getField(column);
					if (field != null) {
						doc.add(field);
					}
				}
				Field field = new LongField("creattime", new Date().getTime(),
						Field.Store.YES);
				doc.add(field);
			}
		} catch (SecurityException e) {
			throw new DataException(e.getMessage(),e);
		} catch (NoSuchMethodException e) {
			throw new DataException(e.getMessage(),e);
		} catch (DataException e) {
			throw e;
		} catch (Exception e) {
			throw new DataException(e.getMessage(),e);
		}
		return doc;
	}

	private Field getField(Column column) {
		Field field = null;
		Object value = column.getValue();
		String fieldName = column.getIndexName();
		// if(ObjectUtil.isEmpty(fieldName)){
		// fieldName = column.getName();
		// }
		fieldName = column.getName();
		Store store = column.isStore() ? Field.Store.YES
				: Field.Store.NO;
		FieldType type = new FieldType();
		type.setIndexed(column.isIndex());
		type.setStored(column.isStore());
		type.setTokenized(column.getFieldType().isToken());
		switch (column.getFieldType()) {
		case booleanx:
			field = new StringField(fieldName, String.valueOf(value), store);
			break;
		case date:
			type.setNumericType(FieldType.NumericType.LONG);
			if (value instanceof java.sql.Date) {
				if (ObjectUtil.isEmpty(value)) {
					field = new LongField(fieldName, 0L, type);
				} else {
					field = new LongField(fieldName,
							((java.sql.Date) value).getTime(), type);
				}
			} else if (value instanceof java.util.Date) {
				if (ObjectUtil.isEmpty(value)) {
					field = new LongField(fieldName, 0L, type);
				} else {
					field = new LongField(fieldName, ((Date) value).getTime(),
							type);
				}
			} else {
				if (ObjectUtil.isEmpty(value)) {
					field = new LongField(fieldName, 0L, type);
				} else {
					field = new LongField(fieldName, Long.parseLong(value
							.toString()), type);
				}
			}
			break;
		case doublex:
			type.setNumericType(FieldType.NumericType.DOUBLE);
			if (ObjectUtil.isEmpty(value)) {
				field = new DoubleField(fieldName, 0D, type);
			} else {
				field = new DoubleField(fieldName, Double.parseDouble(String
						.valueOf(value)), type);
			}
			break;
		case file:
			field = new StringField(fieldName, String.valueOf(value), store);
			break;
		case floatx:
			type.setNumericType(FieldType.NumericType.FLOAT);
			if (ObjectUtil.isEmpty(value)) {
				field = new FloatField(fieldName, 0F, type);
			} else {
				field = new FloatField(fieldName, Float.parseFloat(String
						.valueOf(value)), type);
			}
			break;
		case integer:
			type.setNumericType(FieldType.NumericType.INT);
			if (ObjectUtil.isEmpty(value)) {
				field = new IntField(fieldName, 0, type);
			} else {
				field = new IntField(fieldName, Integer.parseInt(String
						.valueOf(value)), type);
			}
			break;
		case longx:
			type.setNumericType(FieldType.NumericType.LONG);
			if (ObjectUtil.isEmpty(value)) {
				field = new LongField(fieldName, 0L, type);
			} else {
				field = new LongField(fieldName, Long.parseLong(String
						.valueOf(value)), type);
			}
			break;
		case number:
			type.setNumericType(FieldType.NumericType.DOUBLE);
			if (ObjectUtil.isEmpty(value)) {
				field = new DoubleField(fieldName, 0D, type);
			} else {
				field = new DoubleField(fieldName, Double.parseDouble(String
						.valueOf(value)), type);
			}
			break;
		case string:
			field = new StringField(fieldName, String.valueOf(value), store);
			break;
		case text:
			field = new TextField(fieldName, String.valueOf(value), store);
			break;
		case time:
			type.setNumericType(FieldType.NumericType.LONG);
			if (ObjectUtil.isEmpty(value)) {
				field = new LongField(fieldName, 0L, type);
			} else {
				field = new LongField(fieldName, ((Time) value).getTime(), type);
			}
			break;
		case timestamp:
			type.setNumericType(FieldType.NumericType.LONG);
			if (ObjectUtil.isEmpty(value)) {
				field = new LongField(fieldName, 0L, type);
			} else {
				field = new LongField(fieldName, ((Timestamp) value).getTime(),
						type);
			}
			break;
		default:
			field = new StringField(fieldName, String.valueOf(value), store);
			break;
		}
		return field;
	}

	public Formatter getHighlighterFormatter() {
		return new SimpleHTMLFormatter("<font color=\"red\">", "</font>");
	}

	@Override
	public Highlighter getHighlighter(Query query) {
		/** 自定义标注高亮文本标签 */
		Formatter formatter = this.getHighlighterFormatter();
		/** 创建QueryScorer */
		QueryScorer scorer = new QueryScorer(query);
		/** 创建Fragmenter */
		Fragmenter fragmenter = new SimpleSpanFragmenter(scorer);
		Highlighter highlight = new Highlighter(formatter, scorer);
		highlight.setTextFragmenter(fragmenter);
		return highlight;
	}

	@Override
	public <M> M doc2Obj(final Document doc, Class<M> entityClass) {
		return this.doc2Obj(doc, entityClass, null, false);
	}

	@Override
	public <M> M doc2Obj(final Document doc, final Class<M> requiredType,
			final Query query, final boolean high) {
		M model = null;
		try {
			model = requiredType.newInstance();
		} catch (InstantiationException e1) {
			throw new DataException(e1.getMessage(), e1);
		} catch (IllegalAccessException e1) {
			throw new DataException(e1.getMessage(), e1);
		}
		java.lang.reflect.Field[] fields = model.getClass().getDeclaredFields();
		Highlighter highlight = this.getHighlighter(query);
		Analyzer analyzer = this.server.getDefaultAnalyzer();
		for (int i = 0; i < fields.length; i++) {
			java.lang.reflect.Field f = fields[i];
			f.setAccessible(true);
			try {
				this.setValue(f, model, doc, highlight, analyzer, high);
			} catch (DataException e) {
				throw e;
			} catch (Exception e) {
				throw new DataException(e.getMessage(),e);
			}
		}
		return model;
	}

	private void setValue(final java.lang.reflect.Field f, final Object target,
			final Document doc, final Highlighter highlight,
			final Analyzer analyzer, final boolean high) {

		Class<?> classObj = target.getClass();
		if (!this.isCollection(f)) {
			if (this.isJavaClass(f.getType())) { // 该表的字段
				// 获取属性名为name的属性
				java.lang.reflect.Field nameField = null;
				try {
					nameField = classObj.getDeclaredField(f.getName());
					// 设置通过反射访问该Field时取消访问权限检查
					nameField.setAccessible(true);
					Object value = this.getValue(f, f.getName(), doc,
							highlight, analyzer, high);
					// System.out.println(nameField.getName()+":"+value);
					// 设置新的值
					if (value != null) {
						nameField.set(target, value);
					}
				} catch (DataException e) {
					throw e;
				} catch (Exception e) {
					throw new DataException(e.getMessage(),e);
				}
			} else {// 该表的外键
					// 获取属性名为name的属性
				Class<?> fkclass = f.getType();
				try {

					Object fkobj = fkclass.newInstance();
					java.lang.reflect.Field eField = null;
					eField = classObj.getDeclaredField(f.getName());
					// 设置通过反射访问该Field时取消访问权限检查
					eField.setAccessible(true);
					java.lang.reflect.Field nameField = null;
					nameField = fkclass.getDeclaredField(DEFAULT_PK);
					// 设置通过反射访问该Field时取消访问权限检查
					nameField.setAccessible(true);
					Object value = this.getValue(nameField, f.getName(), doc,
							highlight, analyzer, high);
					// System.out.println(nameField.getName()+":"+value);
					if (value != null) {
						nameField.set(fkobj, value);
						eField.set(target, fkobj);
					}
				} catch (DataException e) {
					throw e;
				} catch (Exception e) {
					throw new DataException(e.getMessage(),e);
				}
			}
		}
	}

	/**
	 * 是否为集合类型
	 * 
	 * @author Defender 2014年2月15日 下午1:41:51
	 * @param field
	 * @return
	 */
	private boolean isCollection(java.lang.reflect.Field field) {
		boolean flag = false;
		String typeStr = field.getGenericType().toString();
		if (("interface java.util.Collection".equals(typeStr))
				|| ("interface java.util.HashMap".equals(typeStr))
				|| ("interface java.util.List".equals(typeStr))
				|| ("interface java.util.Map".equals(typeStr))
				|| ("interface java.util.Set".equals(typeStr))
				|| ("class java.util.Collection".equals(typeStr))
				|| ("class java.util.HashMap".equals(typeStr))
				|| ("class java.util.List".equals(typeStr))
				|| ("class java.util.Map".equals(typeStr))
				|| ("class java.util.Set".equals(typeStr))) {
			flag = true;
		}
		return flag;
	}

	/**
	 * 判断是否为java本身的类型
	 * 
	 * @param clz
	 * @return
	 */
	private boolean isJavaClass(Class<?> clz) {
		return clz != null && clz.getClassLoader() == null;
	}

	private String setValueHighlighter(final String fieldName,
			final String value, final Highlighter highlight,
			final Analyzer analyzer, final boolean high) {
		String val = value;
		try {
			if (!(value == null || "".equals(value))
					&& this.isHigherShow(fieldName)) {
				// System.out.println(f.getName()+":"+val);
				TokenStream tokenStream = analyzer.tokenStream(fieldName,
						new StringReader(String.valueOf(val)));
				String valStr = highlight.getBestFragment(tokenStream,
						String.valueOf(val));
				// System.out.println(valStr);
				val = (valStr == null ? val : valStr);
			}
		} catch (DataException e) {
			throw e;
		} catch (Exception e) {
			throw new DataException(e.getMessage(),e);
		}
		return val;
	}

	public boolean isHigherShow(String name) {
		return true;
	}

	@Override
	public Object getValue(final java.lang.reflect.Field f,
			final String indexName, final Document doc,
			final Highlighter highlight, final Analyzer analyzer,
			final boolean high) {

		String val = doc.get(indexName);
		Object value = null;
		if (f.getType().equals(java.sql.Date.class)) {

			if (!StringUtils.isBlank(val) && !"0".equals(val)
					&& !"null".equals(val)) {
				value = new java.sql.Date(new Date(Long.valueOf(val)).getTime());
			}
		} else if (f.getType().equals(java.util.Date.class)) {

			if (!StringUtils.isBlank(val) && !"0".equals(val)
					&& !"null".equals(val)) {
				value = new Date(Long.valueOf(val));
			}
		} else if (f.getType().equals(Timestamp.class)) {

			if (!StringUtils.isBlank(val) && !"0".equals(val)
					&& !"null".equals(val)) {
				value = new Timestamp(new Date(Long.valueOf(val)).getTime());
			}
		} else if (f.getType().equals(Time.class)) {

			if (!StringUtils.isBlank(val) && !"0".equals(val)
					&& !"null".equals(val)) {
				value = new Time(new Date(Long.valueOf(val)).getTime());
			}
		} else if (f.getType().equals(Integer.class)
				|| f.getType().equals(int.class)) {

			if (!StringUtils.isBlank(val) && !"null".equals(val)) {
				value = Integer.valueOf(val);
			}
		} else if (f.getType().equals(Short.class)
				|| f.getType().equals(short.class)) {

			if (!StringUtils.isBlank(val) && !"null".equals(val)) {
				value = Short.valueOf(val);
			}
		} else if (f.getType().equals(Byte.class)
				|| f.getType().equals(byte.class)) {

			if (!StringUtils.isBlank(val) && !"null".equals(val)) {
				value = Byte.valueOf(val);
			}
		} else if (f.getType().equals(Long.class)
				|| f.getType().equals(long.class)) {

			if (!StringUtils.isBlank(val) && !"null".equals(val)) {
				value = Long.valueOf(val);
			}
		} else if (f.getType().equals(Float.class)
				|| f.getType().equals(float.class)) {

			if (!StringUtils.isBlank(val) && !"null".equals(val)) {
				value = Float.valueOf(val);
			}
		} else if (f.getType().equals(Double.class)
				|| f.getType().equals(double.class)) {

			if (!StringUtils.isBlank(val) && !"null".equals(val)) {
				value = Double.valueOf(val);
			}
		} else if (f.getType().equals(Boolean.class)
				|| f.getType().equals(boolean.class)) {

			if (!StringUtils.isBlank(val) && !"null".equals(val)) {
				value = Boolean.valueOf(val);
			}
		} else {
			value = val;
		}
		if (value != null) {
			if (high) {
				if (f.getType().equals(String.class)) {
					value = this.setValueHighlighter(f.getName(), val,
							highlight, analyzer, high);
				}
			}
		}
		return value;
	}

	@Override
	public Field handlFKField(
			final java.lang.reflect.Field fkField, final Object value) {
		Field field = null;
		if (value != null) {
			try {
				Object value1 = BeanParameterUtil.getFieldValue(value,
						DEFAULT_PK);
				field = this.handlField(fkField, value1);
			} catch (DataException e) {
				throw e;
			} catch (Exception e) {
				throw new DataException(e.getMessage(),e);
			}
		}
		return field;
	}

	@Override
	public Field handlField(
			final java.lang.reflect.Field f, final Object value) {
		String fieldName = f.getName();
		Field field = null;
		if (value instanceof java.sql.Date) {
			if (value == null || "".equals(value)) {
				field = new LongField(fieldName, 0L,
						Field.Store.YES);
			} else {
				field = new LongField(fieldName,
						((java.sql.Date) value).getTime(),
						Field.Store.YES);
			}
		} else if (value instanceof java.util.Date) {
			if (value == null || "".equals(value)) {
				field = new LongField(fieldName, 0L,
						Field.Store.YES);
			} else {
				field = new LongField(fieldName, ((Date) value).getTime(),
						Field.Store.YES);
			}
		} else if (value instanceof Timestamp) {
			if (value == null || "".equals(value)) {
				field = new LongField(fieldName, 0L,
						Field.Store.YES);
			} else {
				field = new LongField(fieldName, ((Timestamp) value).getTime(),
						Field.Store.YES);
			}
		} else if (value instanceof Time) {
			if (value == null || "".equals(value)) {
				field = new LongField(fieldName, 0L,
						Field.Store.YES);
			} else {
				field = new LongField(fieldName, ((Time) value).getTime(),
						Field.Store.YES);
			}
		} else if (value instanceof Byte || f.getType().equals(byte.class)) {
			if (value == null || "".equals(value)) {
				field = new IntField(fieldName, 0,
						Field.Store.YES);
			} else {
				field = new IntField(fieldName, Integer.parseInt(String
						.valueOf(value)),
						Field.Store.YES);
			}
		} else if (value instanceof Integer || f.getType().equals(int.class)) {
			if (value == null || "".equals(value)) {
				field = new IntField(fieldName, 0,
						Field.Store.YES);
			} else {
				field = new IntField(fieldName, Integer.parseInt(String
						.valueOf(value)),
						Field.Store.YES);
			}
		} else if (value instanceof Short || f.getType().equals(short.class)) {
			if (value == null || "".equals(value)) {
				field = new IntField(fieldName, 0,
						Field.Store.YES);
			} else {
				field = new IntField(fieldName, Integer.parseInt(String
						.valueOf(value)),
						Field.Store.YES);
			}
		} else if (value instanceof Long || f.getType().equals(long.class)) {
			if (value == null || "".equals(value)) {
				field = new LongField(fieldName, 0L,
						Field.Store.YES);
			} else {
				field = new LongField(fieldName, Long.parseLong(String
						.valueOf(value)),
						Field.Store.YES);
			}
		} else if (value instanceof Float || f.getType().equals(float.class)) {
			if (value == null || "".equals(value)) {
				field = new FloatField(fieldName, 0F,
						Field.Store.YES);
			} else {
				field = new FloatField(fieldName, Float.parseFloat(String
						.valueOf(value)),
						Field.Store.YES);
			}
		} else if (value instanceof Double || f.getType().equals(double.class)) {
			if (value == null || "".equals(value)) {
				field = new DoubleField(fieldName, 0D,
						Field.Store.YES);
			} else {
				field = new DoubleField(fieldName, Double.parseDouble(String
						.valueOf(value)),
						Field.Store.YES);
			}
		} else {
			field = new StringField(fieldName, String.valueOf(value),
					Field.Store.YES);
		}
		return field;
	}

	@Override
	public <M> PageBean query(final Select select, Class<M> requiredType) {
		return this.query(this.getQuery(select.getWhere()), this.getSort(select),
				select.getPage(), select.getRowCount(), requiredType,
				select.high);
	}

	
	@Override
	public <M> PageBean query(final Query query, Sort sort, int page, int pageSize,
			final Class<M> requiredType, final boolean high) {
		IndexSearcher searcher = this.server.acquire();
		int offset = (int) ((page - 1) * pageSize);
		if (offset < 0) {
			offset = 0;
		}
		PageBean pageBean = null;
		List<M> list = null;
		try {
			int n = LuceneUtil.getMinResultSizeByPage(page, pageSize, searcher);
			this.logger.info("全文搜索条件：" + query.toString());
			this.logger.info("order条件：" + sort);
			TopDocs topDocs = null;
			if (sort == null) {
				topDocs = searcher.search(query, null, n);
			} else {
				topDocs = searcher.search(query, null, n, sort);
			}
			list = LuceneUtil.getResult(offset, pageSize, searcher, topDocs, new DocMapper<M>() {
				
				@Override
				public M mapper(Document doc, int row) throws DataException {
					return doc2Obj(doc, requiredType, query, high);
				}
			});
			int totalCount = topDocs.totalHits;// 总记录数
			pageBean = PageBean.getInstance(page, pageSize, totalCount, list);
		} catch (DataException e) {
			throw e;
		} catch (Exception e) {
			throw new DataException(e.getMessage(),e);
		} finally {
			server.release(searcher);
		}
		return pageBean;
	}


	@Override
	public Query getQuery(final Where where) {
		// BooleanQueryBuilder and = BooleanQueryBuilder.builder();
		Query query = null;
		// QueryBuilder builder = new QueryBuilder(this.getAnalyzer());
		// Analyzer analyzer = this.getAnalyzer();
		if (where != null && where.hasCondition()) {
			WhereParser w = new WhereParser(where, true);
			query = (BooleanQuery) w.parse();
		} else {
			query = new MatchAllDocsQuery();
		}
		return query;
	}

	@Override
	public Sort getSort(final Select select) {
		/**
		 * 
		 // 评分降序，评分一样时后索引的排前面 new SortField[] { SortField.FIELD_SCORE, new
		 * SortField(null, SortField.DOC, true) } //
		 * 评分升序，评分一样时后索引的排前面，呵呵，此为最不相关的排前面，挺有趣的 new SortField[] { new
		 * SortField(null, SortField.SCORE, true), new SortField(null,
		 * SortField.DOC, true) }
		 * */
		// 组件排序条件语句
		List<SortField> sortList = new ArrayList<SortField>();
		List<Order> orders = select.getOrderBys();
		if (select.hasOrder()) {
			for (Order indexOrder : orders) {
				SortField.Type type = SortField.Type.STRING;
				if (indexOrder.getName().equals("creattime")) {
					type = SortField.Type.LONG;
				} else if (indexOrder.getName().equals(DEFAULT_PK)) {
					type = SortField.Type.LONG;
				}
				if (indexOrder.getFieldType() != null) {
					ValueType t = IndexUtil.getValueType(indexOrder
							.getFieldType().getType());
					switch (t) {
					case DOUBLE:
						type = SortField.Type.DOUBLE;
						break;
					case FLOAT:
						type = SortField.Type.FLOAT;
						break;
					case LONG:
						type = SortField.Type.LONG;
						break;
					case INT:
						type = SortField.Type.INT;
						break;
					case STRING:
						type = SortField.Type.STRING;
						break;
					default:
						type = SortField.Type.STRING;
						break;
					}
				}
				if (indexOrder.getType() == OrderType.DESC) {
					sortList.add(new SortField(indexOrder.getName(), type, true));
				} else {
					sortList.add(new SortField(indexOrder.getName(), type,
							false));
				}
			}
		} else {
			// sortList.add(new SortField("id", SortField.INT, true));
		}
		Sort sort = null;
		if (sortList != null && sortList.size() > 0) {
			sort = new Sort(sortList.toArray(new SortField[sortList.size()]));
		} else {
			if (select.fullTextQuery) {
				sortList.add(SortField.FIELD_SCORE);
				// sortList.add(new SortField(DEFAULT_PK, SortField.Type.LONG,
				// true));
			}
			if (sortList != null && sortList.size() > 0) {
				sort = new Sort(
						sortList.toArray(new SortField[sortList.size()]));
			}
		}
		return sort;
	}


	@SuppressWarnings("unchecked")
	@Override
	public LuceneServer getServer() {
		return this.server;
	}

	
}
